package org.jslaughter.component.physics.motion;

import org.jslaughter.event.eventtype.MotionEvent;
import org.newdawn.slick.Image;
import org.newdawn.slick.geom.Rectangle;
import org.newdawn.slick.geom.Transform;
import org.newdawn.slick.geom.Vector2f;
import org.nvframe.component.AbstractComponent;
import org.nvframe.component.physics.state.PhysicsPosition;
import org.nvframe.component.state.Position;
import org.nvframe.entity.Entity;
import org.nvframe.event.EventService;
import org.nvframe.event.eventtype.RenderEvent;
import org.nvframe.event.eventtype.RenderListener;
import org.nvframe.event.eventtype.UpdateEvent;
import org.nvframe.event.eventtype.UpdateListener;
import org.nvframe.exception.NVFrameException;
import org.nvframe.manager.ResourceManager;
import org.nvframe.util.settings.SettingsObj;

/**
 * 
 * @author Nik Van Looy
 */
public class BulletMotion extends AbstractComponent implements UpdateListener, RenderListener {

	private float moveSpeed;
	private float offset;
	private Vector2f startCoords;
	private Vector2f velocity = new Vector2f();
	private Image bulletTrail = null;
	private float trailDistance = 0;
	private Rectangle bulletRect;
	
	private boolean moving = false;

	public BulletMotion(String id, Entity owner, SettingsObj settings) throws NVFrameException {
		super(id, owner);
		
		moveSpeed = settings.getFloat("velocity");	
		offset = settings.getFloat("offset", 0);
		
		if(settings.containsKey("bulletTrail")) {
			String trailImage = settings.getString("bulletTrail");
			
			try {
				bulletTrail = ResourceManager.getInstance().getImage(trailImage);
			} catch (NVFrameException e) {
				throw new NVFrameException("cannot load bullettrail - entity: " + owner.getId() + ", bulletTrail: " + trailImage);
			}
		}
		
		EventService.getInstance().addEventListener(this);
	}
	
	/**
	 * 
	 * @param startCoords
	 * @param targetCoords
	 * @param offset
	 */
	public void startMotion(Vector2f startCoords, Vector2f targetCoords, float offset) {
		this.offset = offset;
		startMotion(startCoords.copy(), targetCoords.copy());
	}

	/**
	 * 
	 * @param startCoords
	 * @param targetCoords
	 */
	public void startMotion(Vector2f startCoords, Vector2f targetCoords) {
		this.startCoords = startCoords;

		Position positionComp = (Position) owner.getComponent(Position.class);
		float radDirection = (float) Math.atan2(targetCoords.getY() - startCoords.getY(), 
				targetCoords.getX() - startCoords.getX());

		if(positionComp == null)
			return;

		positionComp.setDirection((float) Math.toDegrees(radDirection));
		
		positionComp.setXY(startCoords.getX() + (float) Math.cos(radDirection) * offset, 
				startCoords.getY() + (float) Math.sin(radDirection) * offset);
		
		velocity.x = (float) Math.cos(radDirection) * moveSpeed;
		velocity.y = (float) Math.sin(radDirection) * moveSpeed;
		
		moving = true;
		
		// init bulletTrail
		if(bulletTrail != null) {
			bulletTrail.setCenterOfRotation(0, bulletTrail.getHeight());
			bulletTrail.setRotation((float) Math.toDegrees(radDirection)-180);
			
			bulletRect = new Rectangle(positionComp.getX(), positionComp.getY(), 0, 1);
			bulletRect.transform(Transform.createRotateTransform(radDirection, 0, 0));
		}
	}

	@Override
	public void onUpdate(UpdateEvent event) {
		int delta = event.getDelta();
		
		if(!moving)
			return;
		
		PhysicsPosition positionComp = (PhysicsPosition) owner.getComponent(PhysicsPosition.class);
		positionComp.adjustVelocity(velocity.x * delta, velocity.y * delta);
		
		EventService.getInstance().fireEvent(new MotionEvent(getOwner()), getOwner());
		
		// bulletTrail
		if(bulletTrail != null) {
			trailDistance = (float) Math.sqrt(Math.pow(positionComp.getX() - startCoords.x, 2) + 
					Math.pow(positionComp.getY() - startCoords.y, 2));
			trailDistance = trailDistance - 40 > 300 ? 300 : trailDistance - 40;
			bulletRect.setWidth(trailDistance);
			bulletRect.setX(positionComp.getX());
			bulletRect.setY(positionComp.getY());
		}
	}
	
	@Override
	public void removed() {
		EventService.getInstance().removeEventListener(this);
	}

	@Override
	public void onRender(RenderEvent event) {
		PhysicsPosition positionComp = (PhysicsPosition) owner.getComponent(PhysicsPosition.class);
		
		bulletTrail.draw(positionComp.getX(), positionComp.getY(), trailDistance, bulletTrail.getHeight());
		//event.getGr().draw(bulletRect);
	}
}
